﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LightCAD.MathLib
{
    public class CylindricalSurface3d : Surface3d
    {
        public double RadiusTop { get; private set; }
        public double RadiusBottom { get; private set; }
        public double StartAngle { get; private set; }
        public double EndAngle { get; private set; }
        public double Height { get; private set; }

        public Vector3 Origin { get; private set; }

        public Vector3 Normal { get; private set; }
        public int RadialSegments { get; private set; }
        public bool Reversal { get; private set; }
        public CylindricalSurface3d(double radiusTop, double radiusBottom, double height, double startAngle, double endAngle, Vector3 origin, Vector3 normal, int radialSegments = 32, bool reversal = false)
        {
            this.RadiusTop = radiusTop;
            this.RadiusBottom = radiusBottom;
            this.Height = height;
            this.StartAngle = startAngle;
            this.EndAngle = endAngle;
            this.Origin = origin;
            this.Normal = normal;
            this.RadialSegments = radialSegments;
            this.Reversal = reversal;
            var topOrigin = origin.Clone().AddScaledVector(normal.Normalize(), height );
            var endOrigin = origin.Clone().AddScaledVector(normal.Normalize(),0);
            var arcTop = new Arc3d(topOrigin, radiusTop, startAngle, endAngle);
            var arcBottom = new Arc3d(endOrigin, radiusBottom, endAngle, startAngle, true);
            this.OuterLoop = new List<Curve3d>
            {
                arcTop,
                new Line3d(arcTop.End, arcBottom.Start),
                arcBottom,
                new Line3d(arcBottom.End, arcTop.Start),
            };
        }

        public override Tuple<double[], int[]> Trianglate()
        {
            var allPoints = new ListEx<Vector3>();
            var indices = new ListEx<int>();
            var topArc = this.OuterLoop[0];
            var endArc = this.OuterLoop[2];
            var topPoints = topArc.GetPoints(this.RadialSegments);
            var endPoints = endArc.GetPoints(this.RadialSegments);
            for (var i=0;i<this.RadialSegments;i++)
            {
                var top = topPoints[i].Clone();
                var topNx = topPoints[i+1].Clone();
                var endNx = endPoints[this.RadialSegments - i - 1].Clone();
                var end = endPoints[this.RadialSegments - i].Clone();
                var teNormal = (end - top).Normalize();
                var teNxNormal = (endNx - topNx).Normalize();
                var len = top.DistanceTo(end);
                var nxlen = topNx.DistanceTo(endNx);
                allPoints.Push(top,topNx);
                allPoints.Push(end, endNx);
                var count = allPoints.Count;
                if (Reversal)
                {
                    indices.Push(count - 4, count - 1, count - 2, count - 4, count - 3, count - 1);
                }
                else
                {
                    indices.Push(count - 4, count - 2, count - 1, count - 4, count - 1, count - 3);
                }
            }
            var posArr = Utils.GenerateVertexArr(allPoints);
            return new Tuple<double[], int[]>(posArr, indices.ToArray());
        }
    }
}
